package member

import (
	"log"
	"net/http"
	"strings"

	"encoding/json"

	"fmt"

	"awfan.cn/utils"

	"gopkg.in/mgo.v2"
	"gopkg.in/mgo.v2/bson"
)

func edit(format, id string, body []byte, w http.ResponseWriter, db *mgo.Database) {
	if id == "" {
		utils.WriteError(format, 404, "#id is empty", w)
		return
	}

	if !bson.IsObjectIdHex(id) {
		utils.WriteError(format, 405, fmt.Sprintf("#id is wrong format: '%v'", id), w)
		return
	}

	data := MEMBER_XML{}

	if err := json.Unmarshal(body, &data); err != nil {
		utils.WriteError(format, 404, err.Error(), w)
		return
	}

	c := db.C(utils.PkgName(MEMBERS_XML{}))

	// disable modify password, name and mail
	data.Password = ""
	data.Name = ""
	data.Mail = ""

	if err := c.UpdateId(bson.ObjectIdHex(id), bson.M{"$set": data}); err != nil {
		utils.WriteError(format, 404, err.Error(), w)
		return
	}
	utils.WriteEmpty(format, w)
}

func modifyPassword(format, code, mail string, body []byte, w http.ResponseWriter, db *mgo.Database) {
	if mail == "" {
		utils.WriteError(format, 404, "#mail is empty", w)
		return
	}

	c := db.C(utils.PkgName(MEMBERS_XML{}))

	q := c.Find(bson.M{
		"mail": bson.RegEx{"^" + mail + "$", "i"},
	})

	var count int
	var err error

	if count, err = q.Count(); err != nil {
		utils.WriteError(format, 401, err.Error(), w)
		return
	}

	if count <= 0 {
		utils.WriteError(format, 402, "#mail not exist", w)
		return
	}

	type p struct {
		Id       bson.ObjectId `bson:"_id"`
		Password string        `json:"password" bson:"password"`
		Token    string        `bson:"token"`
	}

	d := p{}
	if err = json.Unmarshal(body, &d); err != nil {
		utils.WriteError(format, 404, err.Error(), w)
		return
	}

	if strings.TrimSpace(d.Password) == "" {
		utils.WriteError(format, 404, "#password is empty", w)
		return
	}

	if !strings.EqualFold(d.Token, code) {
		utils.WriteError(format, 405, "#mail code not match", w)
		return
	}

	if err = c.UpdateId(d.Id, bson.M{"$set": bson.M{"password": d.Password, "token": ""}}); err != nil {
		utils.WriteError(format, 404, err.Error(), w)
		return
	}

	utils.WriteEmpty(format, w)
}

func modifyDPassword(format, id, token string, body []byte, w http.ResponseWriter, db *mgo.Database) {
	if !bson.IsObjectIdHex(id) {
		utils.WriteError(format, 404, "#id is wrong format", w)
		return
	}

	c := db.C(utils.PkgName(MEMBERS_XML{}))

	q := c.FindId(bson.ObjectIdHex(id))

	var count int
	var err error

	if count, err = q.Count(); err != nil {
		utils.WriteError(format, 401, err.Error(), w)
		return
	}

	if count <= 0 {
		utils.WriteError(format, 402, "#account not exist", w)
		return
	}

	m := MEMBER_XML{}
	if err := q.One(&m); err != nil {
		utils.WriteError(format, 404, err.Error(), w)
		return
	}

	type p struct {
		Password string `json:"password" bson:"password"`
	}

	d := p{}
	if err = json.Unmarshal(body, &d); err != nil {
		utils.WriteError(format, 404, err.Error(), w)
		return
	}

	if strings.TrimSpace(d.Password) == "" {
		utils.WriteError(format, 404, "#password is empty", w)
		return
	}

	log.Println("m", m.Token, ":", token)
	if !strings.EqualFold(m.Token, token) {
		utils.WriteError(format, 405, "#token not match", w)
		return
	}

	if err = c.UpdateId(m.Id, bson.M{"$set": bson.M{"password": d.Password}}); err != nil {
		utils.WriteError(format, 404, err.Error(), w)
		return
	}

	utils.WriteEmpty(format, w)
}

func modifyName(format, id, token string, body []byte, w http.ResponseWriter, db *mgo.Database) {
	if !bson.IsObjectIdHex(id) {
		utils.WriteError(format, 404, "#id is wrong format", w)
		return
	}

	c := db.C(utils.PkgName(MEMBERS_XML{}))

	q := c.FindId(bson.ObjectIdHex(id))

	var count int
	var err error

	if count, err = q.Count(); err != nil {
		utils.WriteError(format, 401, err.Error(), w)
		return
	}

	if count <= 0 {
		utils.WriteError(format, 402, "#account not exist", w)
		return
	}

	m := MEMBER_XML{}
	if err := q.One(&m); err != nil {
		utils.WriteError(format, 404, err.Error(), w)
		return
	}

	if !strings.EqualFold(m.Token, token) {
		utils.WriteError(format, 402, "#token not match", w)
		return
	}

	type p struct {
		Name string `json:"name"`
	}

	d := p{}
	if err = json.Unmarshal(body, &d); err != nil {
		utils.WriteError(format, 404, err.Error(), w)
		return
	}

	if strings.TrimSpace(d.Name) == "" {
		utils.WriteError(format, 404, "#name is empty", w)
		return
	}
	// check name exist

	q = c.Find(bson.M{"name": d.Name, "_id": bson.M{"$ne": bson.ObjectIdHex(id)}})

	if count, err = q.Count(); err != nil {
		utils.WriteError(format, 404, err.Error(), w)
		return
	}

	if count >= 1 {
		utils.WriteError(format, 404, "#name exist", w)
		return
	}

	if err = c.UpdateId(m.Id, bson.M{"$set": bson.M{"name": d.Name}}); err != nil {
		utils.WriteError(format, 404, err.Error(), w)
		return
	}

	utils.WriteEmpty(format, w)
}

func modifyMail(format, id, token string, body []byte, w http.ResponseWriter, db *mgo.Database) {
	if !bson.IsObjectIdHex(id) {
		utils.WriteError(format, 404, "#id is wrong format", w)
		return
	}

	c := db.C(utils.PkgName(MEMBERS_XML{}))

	q := c.FindId(bson.ObjectIdHex(id))

	var count int
	var err error

	if count, err = q.Count(); err != nil {
		utils.WriteError(format, 401, err.Error(), w)
		return
	}

	if count <= 0 {
		utils.WriteError(format, 402, "#account not exist", w)
		return
	}

	m := MEMBER_XML{}
	if err := q.One(&m); err != nil {
		utils.WriteError(format, 404, err.Error(), w)
		return
	}

	if !strings.EqualFold(m.Token, token) {
		utils.WriteError(format, 402, "#token not match", w)
		return
	}

	type p struct {
		Mail string `json:"mail"`
	}

	d := p{}
	if err = json.Unmarshal(body, &d); err != nil {
		utils.WriteError(format, 404, err.Error(), w)
		return
	}

	if strings.TrimSpace(d.Mail) == "" {
		utils.WriteError(format, 404, "#mail is empty", w)
		return
	}
	// check name exist

	q = c.Find(bson.M{"mail": d.Mail, "_id": bson.M{"$ne": bson.ObjectIdHex(id)}})

	if count, err = q.Count(); err != nil {
		utils.WriteError(format, 404, err.Error(), w)
		return
	}

	if count >= 1 {
		utils.WriteError(format, 404, "#mail exist", w)
		return
	}

	if err = c.UpdateId(m.Id, bson.M{"$set": bson.M{"mail": d.Mail}}); err != nil {
		utils.WriteError(format, 404, err.Error(), w)
		return
	}

	utils.WriteEmpty(format, w)
}
